﻿using RockBus.Composition.Interfaces;
using RockBus.DataContracts;
using RockBus.Hosting.Interfaces;
using RockBus.Routing.Interfaces;
using System;
using System.ServiceModel;
using System.ServiceModel.Activation;

namespace RockBus.Hosting.Web
{
    public class DynamicWebReceivePortServiceHostFactory : ServiceHostFactory
    {
        private const string InvalidConstructorString = "The DynamicWebReceivePortServiceHostFactory must be constructed with the proper arguments: PublisherId and ReceivePortId";

        private ISubscriptionConfigurationManager SubscriptionConfigurationManager { get { return DependencyManager.Instance.Resolve<ISubscriptionConfigurationManager>(); } }

        private IReceivePortServiceHostFactory ReceivePortServiceHostFactory { get { return DependencyManager.Instance.Resolve<IReceivePortServiceHostFactory>(); } }

        private IServiceHostManager ServiceHostManager { get { return DependencyManager.Instance.Resolve<IServiceHostManager>(); } }

        public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
        {
            if (string.IsNullOrEmpty(constructorString))
            {
                throw new ApplicationException(InvalidConstructorString);
            }

            // Retrieve RockBus configuration element ids
            var ids = constructorString.Split(';');
            if (ids.Length != 2)
            {
                throw new ApplicationException(InvalidConstructorString);
            }

            var publisherId = ids[0];
            var receivePortId = ids[1];
            if (string.IsNullOrEmpty(publisherId) || string.IsNullOrEmpty(receivePortId))
            {
                throw new ApplicationException(InvalidConstructorString);
            }

            // Get the latest PublisherConfiguration
            var pc = this.SubscriptionConfigurationManager.PublisherConfiguration;

            // Retrieve the corresponding ReceivePortInfo
            ReceivePortInfo rpi = null;
            if ((pc == null) ||
                (!pc.TryFindReceivePortInfo(publisherId, receivePortId, out rpi)) ||
                (rpi == null))
            {
                throw new ApplicationException(
                    string.Format("The PublisherConfiguration for PublisherId {0} and ReceivePortId {1} could not be determined. Verify the PublisherId and ReceivePortId configuration settings.",
                    publisherId,
                    receivePortId));
            }

            var serviceHostBase = this.ReceivePortServiceHostFactory.CreateServiceHost(rpi, baseAddresses);
            this.ServiceHostManager.RegisterDynamicServiceHost(rpi, serviceHostBase);
            return serviceHostBase;
        }
    }
}